package tags;

import groovy.lang.Closure;

import java.io.PrintWriter;
import java.util.List;
import java.util.Map;

import play.templates.FastTags;
import play.templates.GroovyTemplate.ExecutableTemplate;

/**
 * @author Ahmed
 * 
 */
@FastTags.Namespace("jqv")
public class VTags2 extends FastTags {

	/**
	 * Generates a html input element of type checkBox linked to a field in
	 * model or not and validated accordingly. For more info about the generated
	 * validation {@link VTags#getCheckBoxValidation(Map, boolean)}.
	 * 
	 * @param args
	 *            tag attributes
	 * 
	 * @param body
	 *            tag inner body
	 * @param out
	 *            the output writer
	 * @param template
	 *            enclosing template
	 * @param fromLine
	 *            template line number where the tag is defined
	 * @throws Exception
	 * 
	 */
	@SuppressWarnings("unchecked")
	public static void _checkbox(Map<?, ?> args, Closure body, PrintWriter out,
			ExecutableTemplate template, int fromLine) throws Exception {
		String htmlElement = "<input type=\"checkbox\" class=\"%s %s\" id=\"%s\" name=\"%s\" %s />";
		String[] modelField = VTags.getModelField(args);
		String validation = getCheckBoxValidation(args, true);
		Object checked = VTags.getDefaultValue(modelField);

		((Map<Object, Object>) args).put("checked", checked == null ? false
				: checked);

		if (validation == null || validation.isEmpty()) {
			validation = "";
		} else {
			validation = "validate[" + validation + "]";
		}
		htmlElement = VTags.formatHtmlElementAttributes(args, htmlElement,
				modelField, validation);

		out.print(htmlElement);
	}

	/**
	 * Generates a html input element of type Radio Button linked to a field in
	 * model and validated accordingly.
	 * 
	 * @param args
	 *            tag attributes
	 * 
	 * @param body
	 *            tag inner body
	 * @param out
	 *            the output writer
	 * @param template
	 *            enclosing template
	 * @param fromLine
	 *            template line number where the tag is defined
	 * 
	 */
	public static void _radio(Map<?, ?> args, Closure body, PrintWriter out,
			ExecutableTemplate template, int fromLine) {
		// TODO implement radio button element.
	}

	// TODO document _checkBoxList
	/**
	 * @param args
	 *            tag attributes
	 * 
	 * @param body
	 *            tag inner body
	 * @param out
	 *            the output writer
	 * @param template
	 *            enclosing template
	 * @param fromLine
	 *            template line number where the tag is defined
	 * @throws NoSuchFieldException
	 * @throws IllegalAccessException
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * 
	 */
	public static void _checkboxList(Map<?, ?> args, Closure body,
			PrintWriter out, ExecutableTemplate template, int fromLine)
			throws Exception {
		String htmlElement = "<input type=\"checkbox\" class=\"%s %s\" id=\"%s\" name=\"%s\" title=\"%s\" value=\"%s\"/>";
		String valueField = (String) args.remove("value");
		String titleField = (String) args.remove("title");
		List<?> items = (List<?>) args.remove("items");
		if (items.size() == 0) {
			return;
		}
		String checkboxListValidation = getCheckBoxValidation(args, false);
		printTheList(items, items.get(0).getClass(), titleField, valueField,
				htmlElement, out, args, checkboxListValidation);

	}

	// TODO document _radioList
	/**
	 * 
	 * @param args
	 *            tag attributes
	 * 
	 * @param body
	 *            tag inner body
	 * @param out
	 *            the output writer
	 * @param template
	 *            enclosing template
	 * @param fromLine
	 *            template line number where the tag is defined
	 * @throws Exception
	 * 
	 */
	public static void _radioList(Map<?, ?> args, Closure body,
			PrintWriter out, ExecutableTemplate template, int fromLine)
			throws Exception {
		String radioButton = "<input type=\"radio\" class=\"%s %s\" id=\"%s\" name=\"%s\" title=\"%s\" value=\"%s\"/>";
		String value = (String) args.remove("value");
		String title = (String) args.remove("title");
		List<?> items = (List<?>) args.remove("items");
		String validation = (args.remove("required") == null ? "" : "required");

		if (items.size() == 0) {
			return;
		}
		printTheList(items, items.get(0).getClass(), title, value, radioButton,
				out, args, validation);
	}

	/**
	 * Generates a html input element of type select linked to a field in model
	 * and validated accordingly.
	 * 
	 * @param args
	 *            tag attributes
	 * 
	 * @param body
	 *            tag inner body
	 * @param out
	 *            the output writer
	 * @param template
	 *            enclosing template
	 * @param fromLine
	 *            template line number where the tag is defined
	 * 
	 */
	public static void _select(Map<?, ?> args, Closure body, PrintWriter out,
			ExecutableTemplate template, int fromLine) {
		// TODO implement the select Element.
	}

	// TODO document printtheList method
	/**
	 * 
	 * @param items
	 * @param objClass
	 * @param titleField
	 * @param valueField
	 * @param htmlElement
	 * @param out
	 * @param args
	 *            tag attributes
	 * @param validation
	 * @throws Exception
	 */
	public static void printTheList(List<?> items, Class<?> objClass,
			String titleField, String valueField, String htmlElement,
			PrintWriter out, Map<?, ?> args, Object validation)
			throws Exception {
		String label = "<label class=\"%sLbl\" for=\"%s\">%s</label>";
		Object id = args.remove("id");
		Object _class = args.remove("class");
		Object name = args.remove("name");
		boolean horizontal = args.remove("horizontal") != null;
		String separator = "";
		if (horizontal) {
			separator = "&nbsp;&nbsp;&nbsp;&nbsp;";
		} else {
			separator = "<br/>";
		}
		if (id == null) {
			id = titleField;
		}
		if (name == null) {
			name = objClass.getSimpleName();
		}
		if (_class == null) {
			_class = objClass.getSimpleName();
		}

		int i = 1;
		for (Object obj : items) {
			String[] titleValue = new String[2];
			titleValue[0] = VTags.getFieldValue(obj, titleField).toString();
			titleValue[1] = VTags.getFieldValue(obj, valueField).toString();
			// class id title
			out.print(String.format(label, _class, id.toString() + i,
					titleValue[0]) + "&nbsp;");

			if (!validation.toString().isEmpty()) {
				validation = "validate[" + validation + "]";
			}
			// valid class id name title value
			out.println(String.format(htmlElement, validation, _class,
					id.toString() + i, name, titleValue[0], titleValue[1]));
			out.println(separator);
			i++;
		}
	}

	/**
	 * Extracts validation info from the tag attributes {@code arg} that are
	 * valid for inputs of type check box.
	 * 
	 * @param args
	 *            tag attributes
	 * @param isSingle
	 *            to check if the validation for single checkbox or for a group
	 *            of checkboxes.
	 * @return String representing the validation extracted.
	 */
	private static String getCheckBoxValidation(Map<?, ?> args, boolean isSingle) {
		Object minCheckbox = args.remove("min");
		Object maxCheckbox = args.remove("max");
		if (minCheckbox == null) {
			minCheckbox = "";
		} else {
			minCheckbox = "minCheckbox[" + minCheckbox + "]";
		}

		if (maxCheckbox == null) {
			maxCheckbox = "";
		} else {
			maxCheckbox = ",maxCheckbox[" + maxCheckbox + "]";
		}
		if (isSingle) {
			boolean isRequired = args.remove("required") != null;
			Object group = args.remove(",group");
			if (group == null) {
				group = "";
			} else {
				group = "groupRequired[" + group + "]";
			}
			minCheckbox = minCheckbox.toString() + group
					+ (isRequired ? "required" : "");
		}
		return minCheckbox + maxCheckbox.toString();
	}

}
